package cn.edu.neu.softlab633.influencemaximization.sy.model.lt;

import cn.edu.neu.softlab633.influencemaximization.sy.bean.Graph;
import cn.edu.neu.softlab633.influencemaximization.sy.bean.MarginGain;
import cn.edu.neu.softlab633.influencemaximization.sy.datapreprocessing.InfluenceCal.InfluenceCal;
import cn.edu.neu.softlab633.influencemaximization.sy.input.GraphReader;

import java.io.IOException;
import java.util.*;

/**
 * Created by Jason on 2017/5/11.
 */
public class LinearThresholdModel {
    public static MarginGain influencePropagation(double threshold, Double[] query, Collection<Integer> originalList, Graph graph) {
        Set<Integer> candidate = new HashSet<>();
        // 去重
        Set<Integer> originalSet = new HashSet<>();
        originalSet.addAll(originalList);
//        for (Iterator<Integer> iterator = originalList.iterator(); iterator.hasNext(); ) {
//            Integer next = iterator.next();
//            originalSet.add(next);
//        }
        while (true) {
            int currentActivedNum = 0;

            // 集合的出度点且不在集合中的点
            for (Iterator<Integer> iterator = originalSet.iterator(); iterator.hasNext(); ) {
                Integer next = iterator.next();
                ArrayList<Integer> outedge = graph.getOutgoingIndex().getNode(next);
                candidate.addAll(outedge);
            }
            candidate.removeAll(originalSet);

            for (Iterator<Integer> iterator = candidate.iterator(); iterator.hasNext(); ) {
                Integer id = iterator.next();
                if (isActived(threshold, query, id, originalSet, graph)) {
                    originalSet.add(id);
                    currentActivedNum++;
                }
            }
            if (currentActivedNum == 0) {
                break;
            }
        }
        return new MarginGain(originalSet.size(), originalSet);
    }

    private static boolean isActived(double threshold, Double[] query, int id, Collection<Integer> originalSet, Graph graph) {
        ArrayList<Integer> in = graph.getIngoingIndex().getNode(id);
        double influence = 0;
        for (int i = 0; i < in.size(); i++) {
            Integer integer = in.get(i);
            if (influence < threshold) {
                if (originalSet.contains(integer)) {
                    // 计算影响度
                    Double[] tmp = graph.getIngoingIndex().getIndex().get(id).get(integer);
                    influence += InfluenceCal.calInfluence(query, tmp);
                }
            } else {
                return true;
            }
        }
        if (influence < threshold) {
            return false;
        }
        return true;
    }

    public static void main(String[] args) throws IOException {
        Graph graph = GraphReader.graphReaderTest();
        Double[] query = new Double[1];
        query[0] = 1.0;
        ArrayList<Integer> originalSet = new ArrayList<>();
        originalSet.add(21501);
        MarginGain gain = influencePropagation(0.9, query, originalSet, graph);
        System.out.println("能激活的节点数: " + gain.getMarginGainNum());
        for (Iterator<Integer> iterator = gain.getMarginGainNode().iterator(); iterator.hasNext(); ) {
            Integer next = iterator.next();
            ArrayList<Integer> ss = new ArrayList<>();
            ss.add(21501);
            ss.add(next);
            MarginGain tmp = influencePropagation(0.9, query, ss, graph);
            tmp = tmp.sub(gain);
            System.out.println("1能激活的节点 : " + next + " 的边缘增益为: " + tmp.getMarginGainNum());
        }
        System.out.println();
    }
}
